﻿<?php
error_reporting(E_ERROR);

/* Allow the script to hang around waiting for connections. */
set_time_limit(0);

/* Turn on implicit output flushing so we see what we're getting
* as it comes in. */
ob_implicit_flush();

function get_local_ip()
{
	$address = gethostbyname($_ENV['HOSTNAME']);
	if(strlen($address)==0)
	{
		$address='127.0.0.1';
	}
	return $address;
}


$address =get_local_ip();

if(strlen($address)==0)
{
	$address='127.0.0.1';
}
$port = 10007;
function net_api_debug($str)
{
	//echo $str."\r\n";
}


function echo_server($sock,$inbuff,&$outbuff)
{
	echo "input [$inbuff]\r\n";
	$inbuff.="\r\n>";
	$outBuff =$inbuff;
	return 0;
}

function create_tcp_server($address,$port)
{
	if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) 
	{
		net_api_debug( 'socket_create() failed: reason: ' . socket_strerror(socket_last_error()));
		return -1;
	}

	if (($ret = socket_bind($sock, $address, $port)) < 0) 
	{
		net_api_debug('socket_bind() failed: reason: ' . socket_strerror($ret));
		socket_close($sock);
		return -1;
	}

	if (($ret = socket_listen($sock, 5)) < 0) 
	{
		net_api_debug('socket_listen() failed: reason: ' . socket_strerror($ret));
		socket_close($sock);
		return -1;
	}
	net_api_debug( "tcp server listen on $address: $port");
	return $sock;
}

function tcpsend($server_ip,$server_port,$msg_to_send,&$response,$need_response,$timeout_sec,&$msg)
{
	$sock = fsockopen($server_ip,$server_port,$errno,$errstr,$timeout_sec);
	if(!$sock)
	{
		$msg=( "fsockopen($server_ip,$server_port) failed: reason:" . $errstr);
		return -2;
	}
	$ret  =fputs($sock,$msg_to_send);
	if($ret===false)
	{
		$msg=( "fputs($server_ip,$server_port) failed");
		fclose($sock);
		return -3;
	}
	if($need_response)
	{
		$start = time();
		stream_set_timeout($sock,$timeout_sec,0);
		$response='';
		while(!feof($sock))
		{
			//echo 'try fget\r\n';
			if((time()-$start>$timeout_sec))
			{
				break;
			}
			if(($response.=fread($sock,65536))===false)
			{
				$msg = ( "socket_recv($server_ip,$server_port) failed: reason");
				fclose($sock);
				return -4;
			}
			//echo 'after fget [$response]\r\n';
			if(strlen($response)>0)
			{
				break;
			}
		}
	}
	fclose($sock);
	return 0;
}

function tcploop($sock)
{
	echo "start tcp loop\r\n";
	do {
		if (($msgsock = socket_accept($sock)) < 0) 
		{
			echo 'socket_accept() failed: reason: ' . socket_strerror(socket_last_error()) . "\n";
			break;
		}
		socket_getpeername($msgsock,$addr,$port);
		echo "server accpet from  $addr,$port\r\n";
		/* Send instructions. */
		$msg = "\nWelcome to the PHP Test Server. \n" .
		"To quit, type 'quit'. To shut down the server type 'shutdown'.\n";
		//socket_write($msgsock, $msg, strlen($msg));

		do {
			if (false === ($buf = socket_read($msgsock, 2048, PHP_BINARY_READ))) 
			{
				echo 'server:socket_read() failed: reason: ' . socket_strerror(socket_last_error($msgsock)) . "\n";
				break ;
			}
			echo "server read = $buf\r\n";
			if (!$buf = trim($buf)) {
				break;
			}
			if ($buf == 'quit') {
				break;
			}
			if ($buf == 'shutdown') {
				socket_close($msgsock);
				break 2;
			}

			if (strncmp($buf,'mode',4)==0) {
				$func = trim(substr($buf,4));
				echo "your mode change to  [$func]\r\n--------->\r\n";
				continue;
			}
			if(strlen($func)==0)
			{
				$talkback = "PHP: You said \r\n '$buf'.\n";
				echo "server talkback :$talkback\r\n";
				socket_write($msgsock, $talkback, strlen($talkback));

			}
			else
			{
				echo "call $func ,data:[$buf]\r\n";
				$ret = $func($msgsock,$buf,$outbuff);
				if($ret==0)
				{
					socket_write($msgsock,$outbuff,strlen($outbuff));
				}
				else
				{
					break;
				}
			}

		} 
		while (true);
		socket_close($msgsock);
	} 
	while (true);
	socket_close($sock);
}
//------------------------------------------------------------



function udploop($sock)
{


	do 
	{
		var_dump($sock);
		$ret= socket_recvfrom($sock,$buf,65535,0,$client_ip,$client_port);

		if ($ret<=0) 
		{
			echo 'socket_read() failed: reason: ' . socket_strerror($ret) . "\n";
			break ;
		}
		if (!$buf = trim($buf)) 
		{
			continue;
		}
		echo "$client_ip:$client_port: incomming data $buf\r\n".bin2hex($buf)."\r\n";
		if ($buf == 'quit')
		{
			break;
		}
		if ($buf == 'shutdown') 
		{
			socket_close($sock);
			break ;
		}
		$func='';
		if (strncmp($buf,'mode',4)==0) 
		{
			$func = trim(substr($buf,4));
			echo "your mode change to  [$func]\r\n--------->\r\n";
			continue;
		}

		if(strlen($func)==0)
		{
			$outbuff = "PHP: You said '$buf'\r\n";
			socket_sendto($sock,$outbuff,strlen($outbuff),0,$client_ip,$client_port);
			echo "udpserver< :$buf\n";
		}
		else
		{
			echo "call $func ,data:[$buf]\r\n";
			$ret = $func($sock,$buf,$outbuff);
			if($ret==0)
			{
				socket_sendto($sock,$outbuff,strlen($outbuff),0,$client_ip,$client_port);
			}
			else
			{
				break;
			}
		}
	} 
	while (true);
	socket_close($msgsock);

}
function create_udp_socket($address,$port,$block=true,&$msg=NULL)
{
	$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
	if($port>0)
	{
		if(!socket_bind($sock, $address, $port))
		{
			socket_close($sock);
			$msg=  'socket_bind failed: '.socket_strerror(socket_last_error());
		}
	}
	if(!$block)
	{
		$ret = socket_set_nonblock($sock);
		if($ret<0)
		{
			socket_close($sock);
			$msg=  'socket_bind failed: '.socket_strerror(socket_last_error());
			return $ret;
		}
	}
	return $sock;
}

function udpsend($dest_ip,$dest_port,$outbuff,&$resp,$timeout,&$msg=NULL)
{
	global $address;
	$local_port= 0;
	$sock = create_udp_socket($address,$local_port,false,$msg);
	if($sock<0)
	{
		$msg= "create_udp_socket:$msg";
		return -1;
	}

	$ret = socket_sendto($sock,$outbuff,strlen($outbuff),0,$dest_ip,$dest_port);
	if($ret<0)
	{
		$msg= 'socket_sendto: error:'.socket_strerror(socket_last_error());
		socket_close($sock);
		return $ret;
	}
	net_api_debug('udpsend sendto $sock,$ret bytes');
	if($timeout<0)//不需要读返回
	{
		socket_close($sock);
		return $ret;
	}
	$start = time();
	while(time()-$start<$timeout)
	{
		$resp ='';
		//net_api_debug('udpsend recv $sock');
		$ret =socket_recvfrom($sock,$resp,65535,0,$dest_ip,$dest_port);
		//net_api_debug('($errno)'.socket_strerror(socket_last_error($sock)));
		if($ret==0)
		{
			$errno = socket_last_error($sock);
			if($errno==11)
			{
				usleep(50);
				continue;
			}
			else
			{
				break;
			}
		}
		if($ret<0)
		{
			net_api_debug(socket_last_error($errno));
			break;
		}
		if(strlen($resp)>0)
		{
			break;
		}
	}
	socket_close($sock);
	return $ret;
}

?> 
